Panduan komprehensif untuk manajemen sesi SQLAlchemy di Python, dengan fokus pada teknik penanganan transaksi yang kuat untuk memastikan integritas dan konsistensi data.
Manajemen Sesi Python SQLAlchemy: Menguasai Penanganan Transaksi untuk Integritas Data
SQLAlchemy adalah pustaka Python yang kuat dan fleksibel yang menyediakan seperangkat alat komprehensif untuk berinteraksi dengan basis data. Inti dari SQLAlchemy adalah konsep sesi, yang bertindak sebagai zona persiapan untuk semua operasi yang Anda lakukan pada basis data Anda. Manajemen sesi dan transaksi yang tepat sangat penting untuk menjaga integritas data dan memastikan perilaku basis data yang konsisten, terutama dalam aplikasi kompleks yang menangani permintaan bersamaan.
Memahami Sesi SQLAlchemy
Sesi SQLAlchemy mewakili unit kerja, percakapan dengan basis data. Ia melacak perubahan yang dilakukan pada objek, yang memungkinkan Anda menyimpannya ke basis data sebagai operasi atom tunggal. Anggap saja sebagai ruang kerja tempat Anda membuat modifikasi pada data sebelum secara resmi menyimpannya. Tanpa sesi yang dikelola dengan baik, Anda berisiko mengalami inkonsistensi data dan potensi kerusakan.
Membuat Sesi
Sebelum Anda dapat mulai berinteraksi dengan basis data Anda, Anda perlu membuat sesi. Ini melibatkan pertama-tama membangun koneksi ke basis data menggunakan mesin SQLAlchemy.
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
# String koneksi basis data
db_url = 'sqlite:///:memory:' # Ganti dengan URL basis data Anda (mis., PostgreSQL, MySQL)
# Buat mesin
engine = create_engine(db_url, echo=False) # echo=True untuk melihat SQL yang dihasilkan
# Tentukan dasar untuk model deklaratif
Base = declarative_base()
# Tentukan model sederhana
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
email = Column(String)
def __repr__(self):
return f""
# Buat tabel di basis data
Base.metadata.create_all(engine)
# Buat kelas sesi
Session = sessionmaker(bind=engine)
# Buat contoh sesi
session = Session()
Dalam contoh ini:
- Kami mengimpor modul SQLAlchemy yang diperlukan.
- Kami menentukan string koneksi basis data (`db_url`). Contoh ini menggunakan basis data SQLite di memori untuk kesederhanaan, tetapi Anda akan menggantinya dengan string koneksi yang sesuai untuk sistem basis data Anda (misalnya, PostgreSQL, MySQL). Format spesifiknya bervariasi berdasarkan mesin basis data dan driver yang Anda gunakan. Konsultasikan dokumentasi SQLAlchemy dan dokumentasi penyedia basis data Anda untuk format string koneksi yang benar.
- Kami membuat `engine` menggunakan `create_engine()`. Mesin bertanggung jawab untuk mengelola kumpulan koneksi dan komunikasi dengan basis data. Parameter `echo=True` dapat membantu untuk debugging, karena akan mencetak pernyataan SQL yang dihasilkan ke konsol.
- Kami mendefinisikan kelas dasar (`Base`) menggunakan `declarative_base()`. Ini digunakan sebagai kelas dasar untuk semua model SQLAlchemy kami.
- Kami mendefinisikan model `User`, memetakannya ke tabel basis data bernama `users`.
- Kami membuat tabel di basis data menggunakan `Base.metadata.create_all(engine)`.
- Kami membuat kelas sesi menggunakan `sessionmaker(bind=engine)`. Ini mengkonfigurasi kelas sesi untuk menggunakan mesin yang ditentukan.
- Akhirnya, kami membuat contoh sesi menggunakan `Session()`.
Memahami Transaksi
Transaksi adalah urutan operasi basis data yang diperlakukan sebagai satu unit kerja logis. Transaksi mematuhi properti ACID:
- Atomisitas: Semua operasi dalam transaksi berhasil sepenuhnya atau gagal sepenuhnya. Jika ada bagian dari transaksi yang gagal, seluruh transaksi akan di-rollback.
- Konsistensi: Transaksi harus menjaga basis data dalam keadaan yang valid. Ia tidak boleh melanggar batasan atau aturan basis data apa pun.
- Isolasi: Transaksi bersamaan diisolasi satu sama lain. Perubahan yang dibuat oleh satu transaksi tidak terlihat oleh transaksi lain hingga transaksi pertama di-commit.
- Daya Tahan: Setelah transaksi di-commit, perubahannya bersifat permanen dan akan bertahan bahkan jika terjadi kegagalan sistem.
SQLAlchemy menyediakan mekanisme untuk mengelola transaksi, memastikan properti ACID ini dipertahankan.
Penanganan Transaksi Dasar
Operasi transaksi yang paling umum adalah commit dan rollback.
Melakukan Commit Transaksi
Ketika semua operasi dalam transaksi telah berhasil diselesaikan, Anda melakukan commit transaksi. Ini mempertahankan perubahan ke basis data.
try:
# Tambahkan pengguna baru
new_user = User(name='Alice Smith', email='alice.smith@example.com')
session.add(new_user)
# Lakukan commit transaksi
session.commit()
print("Transaksi berhasil di-commit!")
except Exception as e:
# Tangani pengecualian
print(f"Terjadi kesalahan: {e}")
session.rollback()
print("Transaksi di-rollback.")
finally:
session.close()
Dalam contoh ini:
- Kami menambahkan objek `User` baru ke sesi.
- Kami memanggil `session.commit()` untuk mempertahankan perubahan ke basis data.
- Kami membungkus kode dalam blok `try...except...finally` untuk menangani potensi pengecualian.
- Jika terjadi pengecualian, kami memanggil `session.rollback()` untuk membatalkan perubahan apa pun yang dibuat selama transaksi.
- Kami selalu memanggil `session.close()` dalam blok `finally` untuk melepaskan sesi dan mengembalikan koneksi ke kumpulan koneksi. Ini sangat penting untuk menghindari kebocoran sumber daya. Gagal menutup sesi dapat menyebabkan kehabisan koneksi dan ketidakstabilan aplikasi.
Melakukan Rollback Transaksi
Jika terjadi kesalahan selama transaksi, atau jika Anda memutuskan bahwa perubahan tidak boleh dipertahankan, Anda melakukan rollback transaksi. Ini mengembalikan basis data ke keadaan sebelum transaksi dimulai.
try:
# Tambahkan pengguna dengan email yang tidak valid (contoh untuk memaksa rollback)
invalid_user = User(name='Bob Johnson', email='invalid-email')
session.add(invalid_user)
# Commit akan gagal jika email tidak divalidasi di tingkat basis data
session.commit()
print("Transaksi di-commit.")
except Exception as e:
print(f"Terjadi kesalahan: {e}")
session.rollback()
print("Transaksi berhasil di-rollback.")
finally:
session.close()
Dalam contoh ini, jika penambahan `invalid_user` memunculkan pengecualian (misalnya, karena pelanggaran batasan basis data), panggilan `session.rollback()` akan membatalkan upaya penyisipan, membiarkan basis data tidak berubah.
Manajemen Transaksi Tingkat Lanjut
Menggunakan Pernyataan `with` untuk Lingkup Transaksi
Cara yang lebih Pythonic dan kuat untuk mengelola transaksi adalah dengan menggunakan pernyataan `with`. Ini memastikan bahwa sesi ditutup dengan benar, bahkan jika pengecualian terjadi.
from contextlib import contextmanager
@contextmanager
def session_scope():
"""Menyediakan lingkup transaksional di sekitar serangkaian operasi."""
session = Session()
try:
yield session
session.commit()
except Exception:
session.rollback()
raise
finally:
session.close()
# Penggunaan:
with session_scope() as session:
new_user = User(name='Charlie Brown', email='charlie.brown@example.com')
session.add(new_user)
# Operasi dalam blok 'with'
# Jika tidak ada pengecualian yang terjadi, transaksi di-commit secara otomatis.
# Jika terjadi pengecualian, transaksi di-rollback secara otomatis.
print("Pengguna ditambahkan.")
print("Transaksi selesai (di-commit atau di-rollback).")
Fungsi `session_scope` adalah pengelola konteks. Saat Anda memasuki blok `with`, sesi baru dibuat. Saat Anda keluar dari blok `with`, sesi di-commit (jika tidak ada pengecualian yang terjadi) atau di-rollback (jika terjadi pengecualian). Sesi selalu ditutup dalam blok `finally`.
Transaksi Bersarang (Savepoint)
SQLAlchemy mendukung transaksi bersarang menggunakan savepoint. Savepoint memungkinkan Anda melakukan rollback ke titik tertentu dalam transaksi yang lebih besar, tanpa memengaruhi seluruh transaksi.
try:
with session_scope() as session:
user1 = User(name='David Lee', email='david.lee@example.com')
session.add(user1)
session.flush() # Kirim perubahan ke basis data tetapi jangan di-commit dulu
# Buat savepoint
savepoint = session.begin_nested()
try:
user2 = User(name='Eve Wilson', email='eve.wilson@example.com')
session.add(user2)
session.flush()
# Simulasikan kesalahan
raise ValueError("Kesalahan simulasi selama transaksi bersarang")
except Exception as e:
print(f"Kesalahan transaksi bersarang: {e}")
savepoint.rollback()
print("Transaksi bersarang di-rollback ke savepoint.")
# Lanjutkan dengan transaksi luar, user1 masih akan ditambahkan
user3 = User(name='Frank Miller', email='frank.miller@example.com')
session.add(user3)
except Exception as e:
print(f"Kesalahan transaksi luar: {e}")
#Commit akan melakukan commit user1 dan user3, tetapi bukan user2 karena rollback bersarang
try:
with session_scope() as session:
#Verifikasi hanya user1 dan user3 yang ada
users = session.query(User).all()
for user in users:
print(user)
except Exception as e:
print(f"Pengecualian yang Tidak Terduga: {e}") #Seharusnya tidak terjadi
Dalam contoh ini:
- Kami memulai transaksi luar menggunakan `session_scope()`.
- Kami menambahkan `user1` ke sesi dan membersihkan perubahan ke basis data. `flush()` mengirimkan perubahan ke server basis data tetapi *tidak* melakukan commit-nya. Ini memungkinkan Anda untuk melihat apakah perubahan tersebut valid (misalnya, tidak ada pelanggaran batasan) sebelum melakukan commit seluruh transaksi.
- Kami membuat savepoint menggunakan `session.begin_nested()`.
- Di dalam transaksi bersarang, kami menambahkan `user2` dan mensimulasikan kesalahan.
- Kami melakukan rollback transaksi bersarang ke savepoint menggunakan `savepoint.rollback()`. Ini hanya membatalkan perubahan yang dibuat dalam transaksi bersarang (yaitu, penambahan `user2`).
- Kami melanjutkan dengan transaksi luar dan menambahkan `user3`.
- Transaksi luar di-commit, mempertahankan `user1` dan `user3` ke basis data, sementara `user2` dibuang karena rollback savepoint.
Mengontrol Tingkat Isolasi
Tingkat isolasi mendefinisikan tingkat di mana transaksi bersamaan diisolasi satu sama lain. Tingkat isolasi yang lebih tinggi memberikan konsistensi data yang lebih besar tetapi dapat mengurangi konkurensi dan kinerja. SQLAlchemy memungkinkan Anda untuk mengontrol tingkat isolasi transaksi Anda.
Tingkat isolasi umum meliputi:
- Read Uncommitted: Tingkat isolasi terendah. Transaksi dapat melihat perubahan yang belum di-commit yang dibuat oleh transaksi lain. Ini dapat menyebabkan pembacaan kotor.
- Read Committed: Transaksi hanya dapat melihat perubahan yang di-commit yang dibuat oleh transaksi lain. Ini mencegah pembacaan kotor tetapi dapat menyebabkan pembacaan tidak berulang dan pembacaan hantu.
- Repeatable Read: Transaksi dapat melihat data yang sama di seluruh transaksi, bahkan jika transaksi lain memodifikasinya. Ini mencegah pembacaan kotor dan pembacaan tidak berulang tetapi dapat menyebabkan pembacaan hantu.
- Serializable: Tingkat isolasi tertinggi. Transaksi sepenuhnya diisolasi satu sama lain. Ini mencegah pembacaan kotor, pembacaan tidak berulang, dan pembacaan hantu tetapi dapat secara signifikan mengurangi konkurensi.
Tingkat isolasi default tergantung pada sistem basis data. Anda dapat mengatur tingkat isolasi saat membuat mesin atau saat memulai transaksi.
Contoh (PostgreSQL):
from sqlalchemy.dialects.postgresql import dialect
# Atur tingkat isolasi saat membuat mesin
engine = create_engine('postgresql://user:password@host:port/database',
connect_args={'options': '-c statement_timeout=1000'} #Contoh timeout
)
# Atur tingkat isolasi saat memulai transaksi (khusus basis data)
# Untuk postgresql, disarankan untuk mengaturnya pada koneksi, bukan mesin.
from sqlalchemy import event
from sqlalchemy.pool import Pool
@event.listens_for(Pool, "connect")
def set_isolation_level(dbapi_connection, connection_record):
existing_autocommit = dbapi_connection.autocommit
dbapi_connection.autocommit = True
cursor = dbapi_connection.cursor()
cursor.execute("SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE")
dbapi_connection.autocommit = existing_autocommit
cursor.close()
# Kemudian transaksi yang dibuat melalui SQLAlchemy akan menggunakan tingkat isolasi yang dikonfigurasi.
Penting: Metode untuk mengatur tingkat isolasi adalah khusus basis data. Rujuk dokumentasi basis data Anda untuk sintaks yang benar. Mengatur tingkat isolasi secara tidak benar dapat menyebabkan perilaku atau kesalahan yang tidak terduga.
Menangani Konkurensi
Ketika banyak pengguna atau proses mengakses data yang sama secara bersamaan, sangat penting untuk menangani konkurensi dengan benar untuk mencegah kerusakan data dan memastikan konsistensi data. SQLAlchemy menyediakan beberapa mekanisme untuk menangani konkurensi, termasuk penguncian optimis dan penguncian pesimis.
Penguncian Optimis
Penguncian optimis mengasumsikan bahwa konflik jarang terjadi. Ini memeriksa modifikasi yang dilakukan oleh transaksi lain sebelum melakukan commit transaksi. Jika konflik terdeteksi, transaksi akan di-rollback.
Untuk mengimplementasikan penguncian optimis, Anda biasanya menambahkan kolom versi ke tabel Anda. Kolom ini secara otomatis bertambah setiap kali baris diperbarui.
from sqlalchemy import Column, Integer, String, Integer
from sqlalchemy.orm import declarative_base
Base = declarative_base()
class Article(Base):
__tablename__ = 'articles'
id = Column(Integer, primary_key=True)
title = Column(String)
content = Column(String)
version = Column(Integer, nullable=False, default=1)
def __repr__(self):
return f""
#Di dalam blok coba tangkap
def update_article(session, article_id, new_content):
article = session.query(Article).filter_by(id=article_id).first()
if article is None:
raise ValueError("Artikel tidak ditemukan")
original_version = article.version
# Perbarui konten dan tambahkan versi
article.content = new_content
article.version += 1
# Upaya untuk memperbarui, memeriksa kolom versi dalam klausa WHERE
rows_affected = session.query(Article).filter(
Article.id == article_id,
Article.version == original_version
).update({
Article.content: new_content,
Article.version: article.version
}, synchronize_session=False)
if rows_affected == 0:
session.rollback()
raise ValueError("Konflik: Artikel telah diperbarui oleh transaksi lain.")
session.commit()
Dalam contoh ini:
- Kami menambahkan kolom `version` ke model `Article`.
- Sebelum memperbarui artikel, kami menyimpan nomor versi saat ini.
- Dalam pernyataan `UPDATE`, kami menyertakan klausa `WHERE` yang memeriksa apakah kolom versi masih sama dengan nomor versi yang disimpan. `synchronize_session=False` mencegah SQLAlchemy memuat objek yang diperbarui lagi; kami secara eksplisit menangani penomoran versi.
- Jika kolom versi telah diubah oleh transaksi lain, pernyataan `UPDATE` tidak akan memengaruhi baris mana pun (rows_affected akan menjadi 0), dan kami memunculkan pengecualian.
- Kami melakukan rollback transaksi dan memberi tahu pengguna bahwa konflik telah terjadi.
Penguncian Pesimis
Penguncian pesimis mengasumsikan bahwa konflik kemungkinan terjadi. Ia memperoleh kunci pada baris atau tabel sebelum memodifikasinya. Ini mencegah transaksi lain memodifikasi data hingga kunci dilepaskan.
SQLAlchemy menyediakan beberapa fungsi untuk mendapatkan kunci, seperti `with_for_update()`.
# Contoh menggunakan PostgreSQL
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, declarative_base
# Penyiapan basis data (ganti dengan URL basis data Anda yang sebenarnya)
db_url = 'postgresql://user:password@host:port/database'
engine = create_engine(db_url, echo=False) #Set echo to true if you would like to see the SQL generated
Base = declarative_base()
class Item(Base):
__tablename__ = 'items'
id = Column(Integer, primary_key=True)
name = Column(String)
value = Column(Integer)
def __repr__(self):
return f"- "
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
#Fungsi untuk memperbarui item (di dalam coba/kecuali)
def update_item_value(session, item_id, new_value):
# Dapatkan kunci pesimis pada item
item = session.query(Item).filter(Item.id == item_id).with_for_update().first()
if item is None:
raise ValueError("Item tidak ditemukan")
# Perbarui nilai item
item.value = new_value
session.commit()
return True
Dalam contoh ini:
- Kami menggunakan `with_for_update()` untuk mendapatkan kunci pada baris `Item` sebelum memperbaruinya. Ini mencegah transaksi lain memodifikasi baris hingga transaksi saat ini di-commit atau di-rollback. Fungsi `with_for_update()` adalah khusus basis data; konsultasikan dokumentasi basis data Anda untuk detailnya. Beberapa basis data mungkin memiliki mekanisme atau sintaks penguncian yang berbeda.
Penting: Penguncian pesimis dapat mengurangi konkurensi dan kinerja, jadi gunakan hanya jika perlu.
Praktik Terbaik Penanganan Pengecualian
Penanganan pengecualian yang tepat sangat penting untuk memastikan integritas data dan mencegah kerusakan aplikasi. Selalu bungkus operasi basis data Anda dalam blok `try...except` dan tangani pengecualian yang sesuai.
Berikut adalah beberapa praktik terbaik untuk penanganan pengecualian:
- Tangkap pengecualian tertentu: Hindari menangkap pengecualian umum seperti `Exception`. Tangkap pengecualian tertentu seperti `sqlalchemy.exc.IntegrityError` atau `sqlalchemy.exc.OperationalError` untuk menangani berbagai jenis kesalahan secara berbeda.
- Rollback transaksi: Selalu lakukan rollback transaksi jika terjadi pengecualian.
- Catat pengecualian: Catat pengecualian untuk membantu mendiagnosis dan memperbaiki masalah. Sertakan konteks sebanyak mungkin dalam log Anda (misalnya, ID pengguna, data input, stempel waktu).
- Tingkatkan kembali pengecualian jika sesuai: Jika Anda tidak dapat menangani pengecualian, tingkatkan kembali untuk memungkinkan penangan tingkat yang lebih tinggi untuk menanganinya.
- Bersihkan sumber daya: Selalu tutup sesi dan lepaskan sumber daya lainnya dalam blok `finally`.
import logging
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, declarative_base
from sqlalchemy.exc import IntegrityError, OperationalError
# Konfigurasikan logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# Penyiapan basis data (ganti dengan URL basis data Anda yang sebenarnya)
db_url = 'postgresql://user:password@host:port/database'
engine = create_engine(db_url, echo=False)
Base = declarative_base()
class Product(Base):
__tablename__ = 'products'
id = Column(Integer, primary_key=True)
name = Column(String)
price = Column(Integer)
def __repr__(self):
return f""
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
# Fungsi untuk menambahkan produk
def add_product(session, name, price):
try:
new_product = Product(name=name, price=price)
session.add(new_product)
session.commit()
logging.info(f"Produk '{name}' berhasil ditambahkan.")
return True
except IntegrityError as e:
session.rollback()
logging.error(f"IntegrityError: {e}")
#Tangani pelanggaran batasan basis data (misalnya, nama duplikat)
return False
except OperationalError as e:
session.rollback()
logging.error(f"OperationalError: {e}")
#Tangani kesalahan koneksi atau masalah operasional lainnya
return False
except Exception as e:
session.rollback()
logging.exception(f"Terjadi kesalahan yang tidak terduga: {e}")
# Tangani kesalahan tak terduga lainnya
return False
finally:
session.close()
Dalam contoh ini:
- Kami mengkonfigurasi logging untuk merekam peristiwa selama proses.
- Kami menangkap pengecualian tertentu seperti `IntegrityError` (untuk pelanggaran batasan) dan `OperationalError` (untuk kesalahan koneksi).
- Kami melakukan rollback transaksi dalam blok `except`.
- Kami mencatat pengecualian menggunakan modul `logging`. Metode `logging.exception()` secara otomatis menyertakan jejak tumpukan dalam pesan log.
- Kami meningkatkan kembali pengecualian jika kami tidak dapat menanganinya.
- Kami menutup sesi dalam blok `finally`.
Kumpulan Koneksi Basis Data
SQLAlchemy menggunakan kumpulan koneksi untuk mengelola koneksi basis data secara efisien. Kumpulan koneksi mempertahankan sekumpulan koneksi terbuka ke basis data, memungkinkan aplikasi untuk menggunakan kembali koneksi yang ada alih-alih membuat yang baru untuk setiap permintaan. Ini dapat secara signifikan meningkatkan kinerja, terutama dalam aplikasi yang menangani sejumlah besar permintaan bersamaan.
Fungsi `create_engine()` SQLAlchemy secara otomatis membuat kumpulan koneksi. Anda dapat mengkonfigurasi kumpulan koneksi dengan meneruskan argumen ke `create_engine()`.
Parameter kumpulan koneksi umum meliputi:
- pool_size: Jumlah maksimum koneksi dalam kumpulan.
- max_overflow: Jumlah koneksi yang dapat dibuat di luar pool_size.
- pool_recycle: Jumlah detik setelah koneksi didaur ulang.
- pool_timeout: Jumlah detik untuk menunggu koneksi menjadi tersedia.
engine = create_engine('postgresql://user:password@host:port/database',
pool_size=5, #Ukuran kumpulan maksimum
max_overflow=10, #Overflow maksimum
pool_recycle=3600, #Daur ulang koneksi setelah 1 jam
pool_timeout=30
)
Penting: Pilih pengaturan kumpulan koneksi yang sesuai berdasarkan kebutuhan aplikasi Anda dan kemampuan server basis data Anda. Kumpulan koneksi yang dikonfigurasi dengan buruk dapat menyebabkan masalah kinerja atau kehabisan koneksi.
Transaksi Asinkron (Async SQLAlchemy)
Untuk aplikasi modern yang membutuhkan konkurensi tinggi, terutama yang dibangun dengan kerangka kerja asinkron seperti FastAPI atau AsyncIO, SQLAlchemy menawarkan versi asinkron yang disebut Async SQLAlchemy.
Async SQLAlchemy menyediakan versi asinkron dari komponen inti SQLAlchemy, yang memungkinkan Anda untuk melakukan operasi basis data tanpa memblokir loop peristiwa. Ini dapat secara signifikan meningkatkan kinerja dan skalabilitas aplikasi Anda.
Berikut adalah contoh dasar penggunaan Async SQLAlchemy:
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String
import asyncio
# Penyiapan basis data (ganti dengan URL basis data Anda yang sebenarnya)
db_url = 'postgresql+asyncpg://user:password@host:port/database'
engine = create_async_engine(db_url, echo=False)
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
email = Column(String)
def __repr__(self):
return f""
async def create_db_and_tables():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
async def add_user(name, email):
async with AsyncSession(engine) as session:
new_user = User(name=name, email=email)
session.add(new_user)
await session.commit()
async def main():
await create_db_and_tables()
await add_user("Async User", "async.user@example.com")
if __name__ == "__main__":
asyncio.run(main())
Perbedaan utama dari SQLAlchemy sinkron:
- `create_async_engine` digunakan alih-alih `create_engine`.
- `AsyncSession` digunakan alih-alih `Session`.
- Semua operasi basis data bersifat asinkron dan harus ditunggu menggunakan `await`.
- Driver basis data asinkron (misalnya, `asyncpg` untuk PostgreSQL) harus digunakan.
Penting: Async SQLAlchemy memerlukan driver basis data yang mendukung operasi asinkron. Pastikan Anda telah menginstal dan mengkonfigurasi driver yang benar.
Kesimpulan
Menguasai manajemen sesi dan transaksi SQLAlchemy sangat penting untuk membangun aplikasi Python yang kuat dan andal yang berinteraksi dengan basis data. Dengan memahami konsep sesi, transaksi, tingkat isolasi, dan konkurensi, dan dengan mengikuti praktik terbaik untuk penanganan pengecualian dan pengumpulan koneksi, Anda dapat memastikan integritas data dan mengoptimalkan kinerja aplikasi Anda.
Apakah Anda membangun aplikasi web kecil atau sistem perusahaan skala besar, SQLAlchemy menyediakan alat yang Anda butuhkan untuk mengelola interaksi basis data Anda secara efektif. Ingatlah untuk selalu memprioritaskan integritas data dan menangani potensi kesalahan dengan baik untuk memastikan keandalan aplikasi Anda.
Pertimbangkan untuk menjelajahi topik lanjutan seperti:
- Two-Phase Commit (2PC): Untuk transaksi yang mencakup beberapa basis data.
- Sharding: Untuk mendistribusikan data di beberapa server basis data.
- Migrasi basis data: Menggunakan alat seperti Alembic untuk mengelola perubahan skema basis data.